# -=- encoding: utf-8

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse

class OrderedModel(models.Model):
    order = models.PositiveIntegerField(editable=False)

    def save(self, force_insert=False, force_update=False):
        if not self.id:
            try:
                self.order = self.__class__.objects.all().order_by("-order")[0].order + 1
            except IndexError:
                self.order = 0
        super(OrderedModel, self).save(force_insert, force_update)
        

    def order_link(self):
        model_type_id = ContentType.objects.get_for_model(self.__class__).id
        model_id = self.id
        kwargs = {"direction": "up", "model_type_id": model_type_id, "model_id": model_id}
        url_up = reverse("admin-move", kwargs=kwargs)
        kwargs["direction"] = "down"
        url_down = reverse("admin-move", kwargs=kwargs)
        return '<a href="%s">up</a> | <a href="%s">down</a>' % (url_up, url_down)
    order_link.allow_tags = True
    order_link.short_description = 'Move'
    order_link.admin_order_field = 'order'


    @staticmethod
    def move_down(model_type_id, model_id):
        try:
            ModelClass = ContentType.objects.get(id=model_type_id).model_class()

            lower_model = ModelClass.objects.get(id=model_id)
            # higher_model = ModelClass.objects.filter(order__gt=lower_model.order)[0]
            higher_model = ModelClass.objects.get(order=lower_model.order + 1)
            
            lower_model.order, higher_model.order = higher_model.order, lower_model.order

            higher_model.save()
            lower_model.save()
        except IndexError:
            pass
        except ModelClass.DoesNotExist:
            pass
                
    @staticmethod
    def move_up(model_type_id, model_id):
        try:
            ModelClass = ContentType.objects.get(id=model_type_id).model_class()

            higher_model = ModelClass.objects.get(id=model_id)
            # lower_model = ModelClass.objects.filter(order__lt=higher_model.order)[0]
            lower_model = ModelClass.objects.get(order=higher_model.order - 1)

            lower_model.order, higher_model.order = higher_model.order, lower_model.order

            higher_model.save()
            lower_model.save()
        except IndexError:
            pass
        except ModelClass.DoesNotExist:
            pass

    class Meta:
        ordering = ["order"]
        abstract = True

class Taggable:
    "Methoden für tagbare Objekte"
    def tag_with(self, *args):
        for elem in args:
            tmp_tag, created = Tag.objects.get_or_create(name=elem)
            
            ### tagging, created = self.taggings.get_or_create(tag=tmp_tag) # geht leider net, warum auch immer?
            if not self.is_tagged_with(tmp_tag.name):
                tagging = self.taggings.create(tag=tmp_tag)
                tmp_tag.inc_count()
            else:
                tagging = self.taggings.get(tag=tmp_tag)
    
    def remove_tag(self, *args):
        for elem in args:
            if self.is_tagged_with(elem):
                self.taggings.get(tag__name=elem).delete()
                tmp_tag.inc_count(False)
    
    def is_tagged_with(self, tag_name):
        if self.taggings.filter(tag__name=tag_name).count():
            return True
        return False
    
    def tag_list(self, give_me_objects=True):
        list = []
        for tagging in self.taggings.all():
            if give_me_objects:
                element = tagging.tag
            else:
                element = tagging.tag.name
            list.append(element)
        return list
    
    def tags(self):
        return self.tag_list(False)
    
    def clear_tags(self):
        for tagging in self.taggings.all():
            tagging.tag.inc_count(False)
        self.taggings.all().delete()
        
    def count_tags(self):
        return self.taggings.count()

class Usercreated(models.Model, Taggable):
    "Datenfelder für alle benutzergenerierten Daten."
    created_by  = models.ForeignKey   (to = User,      verbose_name = u"Autor",                            help_text = u"Benutzer, der den Content erzeugt hat.", related_name = "%(class)s_created_set" )
    created     = models.DateTimeField(                verbose_name = u"erfasst am",  auto_now_add = True, help_text = u"Datum, zu dem der Content erzeugt wurde." )
    modified_by = models.ForeignKey   (to = User,      verbose_name = u"geändert von",                     help_text = u"Benutzer, der den Content geändert hat.", related_name = "%(class)s_modified_set" )
    modified    = models.DateTimeField(                verbose_name = u"geändert am", auto_now = True,     help_text = u"Datum, zu dem eine Änderung durchgeführt wurde." )
    
    def __unicode__(self):
        return u"von %s" % self.created_by.username
    
    class Meta:
        abstract = True
        ordering = ['-created', 'created_by']
        verbose_name = u"Benutzergeneriertes Objekt"
        verbose_name_plural = u"Benutzergenerierte Objekte"